package com.wlp.auroralusa.rank.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wlp.auroralusa.rank.dao.master.DelayRecordDao;
import com.wlp.auroralusa.rank.dao.master.MasterUserRankDao;
import com.wlp.auroralusa.rank.dao.second.SecondUserRankDao;
import com.wlp.auroralusa.rank.dao.three.ThreeUserRankDao;
import com.wlp.auroralusa.rank.model.DelayRecord;
import com.wlp.auroralusa.rank.model.UserRank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: wanglp
 */
@Service
public class UserRankService extends ServiceImpl<MasterUserRankDao, UserRank> {
    @Autowired
    private MasterUserRankDao masterUserRankDao;
    @Autowired
    private SecondUserRankDao secondUserRankDao;
    @Autowired
    private ThreeUserRankDao threeUserRankDao;
    @Autowired
    private DelayRecordDao delayRecordDao;
    /**
     * 更新rank数据
     */
    @Scheduled(fixedDelay = 10)
    public void updRank(){
        List<UserRank> list = IntStream.range(1,41)
                .mapToObj(id-> new UserRank().setId(id).setScore(RandomUtil.randomDouble(50,100)).setCreateTime(new Date()).setUpdateTime(new Date()))
                .collect(Collectors.toList());
        masterUserRankDao.batchUpd(list);
//        System.out.println("更新完成");
    }

    public void top10(){
        System.out.println(JSONUtil.toJsonStr(baseMapper.top10()));
        System.out.println(JSONUtil.toJsonStr(secondUserRankDao.top10()));
        System.out.println(JSONUtil.toJsonStr(threeUserRankDao.top10()));
    }
    private final int DELAY = 500;
//    @Scheduled(fixedDelay = DELAY)
    public void look(){
        final long it = System.currentTimeMillis();
        Mono.fromRunnable(()-> lookRank(2,it)).subscribeOn(Schedulers.newParallel("rank",10)).subscribe();
        Mono.fromRunnable(()-> lookRank(1,it)).subscribeOn(Schedulers.newParallel("rank",10)).subscribe();
        Mono.fromRunnable(()-> lookRank(0,it)).subscribeOn(Schedulers.newParallel("rank",10)).subscribe();
    }
    public void lookRank(int type,long inTime){
        List<UserRank> so;
        String title ;
        switch (type){
            case 1:{
                //sg 新加坡
                title="sig";
                so = secondUserRankDao.top10();
                break;
            }
            case 2:{
                //悉尼
                title="syd";
                so = threeUserRankDao.top10();
                break;
            }
            default:{
                // 美西
                title="usa";
                so = baseMapper.top10();
            }
        }

        final String finalTitle = title;
        Optional.ofNullable(so).ifPresent(set->{
//            System.out.println(finalTitle +inTime+"-"+System.currentTimeMillis()+"top10:"+JSONUtil.toJsonStr(set.stream().map(o->{
//                UserRank p = new UserRank();
//                p.setId(o.getId()).setScore(o.getScore());
//                return p;
//            }).collect(Collectors.toList())));
            build(inTime,so,type,finalTitle);
        });
        so.clear();
    }
    public static Map<String,String> peopleList = new ConcurrentHashMap<>(100);
    public void build(long ct, UserRank people, int type, String title){
        String key = type + "-" + people.getId();
        if(type!=0){
            if(peopleList.containsKey(key)){
                String[] tv = peopleList.get(key).split("-");
                double score = Double.parseDouble(tv[1]);
                if(score != people.getScore()){
                    String de = 0 + "-" + people.getId();
                    if(peopleList.containsKey(de)){
                        String[] dev = peopleList.get(de).split("-");
                        long dev_last = Long.valueOf(dev[0]);
                        double dev_score = Double.parseDouble(dev[1]);
                        if(dev_score == people.getScore()){
                            delayRecordDao.insert(new DelayRecord().setDelay(Math.toIntExact(ct - dev_last - DELAY)).setArea(title));
                        }
                    }
                }
            }
        }
        if(peopleList.containsKey(key)){
            String[] tv = peopleList.get(key).split("-");
            double score = Double.valueOf(tv[1]);
            if(score != people.getScore()){
                peopleList.put(key,ct+ "-" + people.getScore());
            }
        }else {
            peopleList.put(key,ct+ "-" + people.getScore());
        }
    }
    public void build(long ct,List<UserRank> so,int type,String title){
        String rankStr = so.stream().sorted(Comparator.comparing(UserRank::getScore))
                .map(o->o.getId()+":"+o.getScore()).collect(Collectors.joining("|"));
        String key = String.valueOf(type);
        if(type!=0){
            if(peopleList.containsKey(key)){
                String[] tv = peopleList.get(key).split("-");
                String score = tv[1];
                if(!score.equals(rankStr)){
                    String de = "0";
                    if(peopleList.containsKey(de)){
                        String[] dev = peopleList.get(de).split("-");
                        long dev_last = Long.valueOf(dev[0]);
                        String dev_score = dev[1];
                        if(dev_score.equals(rankStr)){
                            System.out.println(rankStr);
                            System.out.println(JSONUtil.toJsonStr(peopleList));
                            delayRecordDao.insert(new DelayRecord().setDelay(Math.toIntExact(ct - dev_last - DELAY)).setArea(title));
                        }
                    }
                }
            }
        }
        if(peopleList.containsKey(key)){
            String[] tv = peopleList.get(key).split("-");
            String score = tv[1];
            if(!score.equals(rankStr)){
                peopleList.put(key,ct+ "-" + rankStr);
            }
        }else {
            peopleList.put(key,ct+ "-" + rankStr);
        }
    }
}
